﻿/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

using System;

namespace SharpMixLib
{
    /// <summary>
    /// 
    /// </summary>
    public class Word
    {
        /// <summary>
        /// 
        /// </summary>
        private Byte[] bytes = new Byte[6];

        #region Accessors
        /// <summary>
        /// 
        /// </summary>
        public Byte[] Bytes
        {
            get
            {
                return bytes;
            }
            set
            {
                bytes = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public Byte Sign
        {
            get
            {
                return bytes[0];
            }
            set
            {
                bytes[0] = value;
            }
        }

        /// <summary>
        ///     Get: Returns true if this word's sign is positive
        ///     Set: Sets whether the sign is positive (true) or negative (false)
        /// </summary>
        public bool Positive
        {
            get
            {
                if (Bytes[0].Value == 1)
                    return true;
                return false;
            }
            set
            {
                if (value == true)
                    Bytes[0].Value = 1;
                else
                    Bytes[0].Value = 0;
            }
        }

        /// <summary>
        ///     Get: Returns true if this word's sign is negative
        ///     Set: Sets whether the sign is positive (false) or negative (true)
        /// </summary>
        public bool Negative
        {
            get
            {
                if (Bytes[0].Value == 0)
                    return true;
                return false;
            }
            set
            {
                if (value == true)
                    Bytes[0].Value = 0;
                else
                    Bytes[0].Value = 1;
            }
        }
        #endregion

        #region Constructors
        /// <summary>
        /// 
        /// </summary>
        public Word()
        {
            for (int i = 0; i < 6; i++)
            {
                Bytes[i] = new Byte();
            }
        }
        #endregion

        #region Operators
        /// <summary>
        /// 
        /// </summary>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        /// <returns></returns>
        public static Word operator +(Word lhs, Word rhs)
        {
            Word res = new Word();
            for (int i = 1; i < 6; ++i)
            {
                res.Bytes[i].Value = lhs.Bytes[i].Value + rhs.Bytes[i].Value;
            }
            return res;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        /// <returns></returns>
        public static Word operator -(Word lhs, Word rhs)
        {
            Word res = new Word();
            for (int i = 1; i < 6; ++i)
            {
                res.Bytes[i].Value = lhs.Bytes[i].Value - rhs.Bytes[i].Value;
            }
            return res;
        }
        #endregion

        /// <summary>
        ///     Returns a word containing just the bytes
        ///     specified by the field indicators
        /// </summary>
        /// <param name="field">
        ///     Field indicator
        /// </param>
        /// <returns>
        ///     The new word
        /// </returns>
        public Word GetWordByField(int field)
        {
            int right = field % 8;
            int left = (field - right) / 8;

            if (left > right)
                throw new Exception("Left Field indicator is bigger than" +
                    "right indicator");

            if (left < 0 || left > 5)
                throw new Exception("Left field indicator out of bound");

            if (right > 5)
                throw new Exception("Right field indicator out of bound");

            Word word = new Word();
            Byte tmpbyte = Bytes[right];

            for (int i = 5; i >= left; i--)
            {
                word.Bytes[i] = tmpbyte;
            }
            return word;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="field"></param>
        /// <param name="data"></param>
        public void SetWordByField(int field, Word word)
        {
            int right = field % 8;
            int left = (field - right) / 8;
            for (int i = left; i <= right; i++)
            {
                Bytes[i] = word.Bytes[i];
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public int GetTotalValue()
        {
            return Bytes[5].Value;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="right"></param>
        /// <returns></returns>
        public int GetTotalValue(int right)
        {
            return Bytes[right].Value;
        }

        /// <summary>
        ///     Shifts the word one to the left
        /// </summary>
        /// <returns>
        ///     Returns the leftmost byte that gets shiftet out
        /// </returns>
        public Byte ShiftLeft()
        {
            Byte res = Bytes[1];

            for (int i = 1; i < 5; ++i)
            {
                Bytes[i].Value = Bytes[i + 1].Value;
            }
            Bytes[5].Value = 0;
            return res;
        }

        /// <summary>
        ///     Shifts the word one to the right
        /// </summary>
        /// <returns>
        ///     Returns the rightmost byte that gets shiftet out
        /// </returns>
        public Byte ShiftRight()
        {
            Byte res = Bytes[5];

            for (int i = 5; i > 1; --i)
            {
                Bytes[i].Value = Bytes[i - 1].Value;
            }
            Bytes[1].Value = 0;
            return res;
        }

        /// <summary>
        /// 
        /// </summary>
        public void PrintOut()
        {
            System.Console.WriteLine(Bytes[1].Value + ":"
                + Bytes[2].Value + ":"
                + Bytes[3].Value + ":"
                + Bytes[4].Value + ":"
                + Bytes[5].Value);
        }
    }
}
